package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.NcUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.querydata.ShowNcStandard;
import com.ruoyi.system.mapper.NcStandardMapper;
import com.ruoyi.system.service.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 标准主 服务层实现
 *
 * @author ruoyi
 * @date 2019-07-28
 */
@Service
public class NcStandardServiceImpl implements INcStandardService {

    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Autowired
    private NcStandardMapper ncStandardMapper;

    @Autowired
    private INcCaiService ncCaiService;

    @Autowired
    private INcStageService stageService;

    @Autowired
    private INcWorkService workService;

    @Autowired
    private INcPlanService planService;

    @Autowired
    private INcStageMirrorService stageMirrorService;

    @Autowired
    private INcWorkMirrorService workMirrorService;

    @Autowired
    private INcWorkLogService workLogService;

    @Autowired
    private INcMeterialService meterialService;

    /**
     * 查询标准主信息
     *
     * @param standardId 标准主ID
     * @return 标准主信息
     */
    @Override
    public NcStandard selectNcStandardById(Long standardId) {
        return ncStandardMapper.selectNcStandardById(standardId);
    }

    /**
     * 查询标准主列表
     *
     * @param ncStandard 标准主信息
     * @return 标准主集合
     */
    @Override
    public List<NcStandard> selectNcStandardList(NcStandard ncStandard) {
        return ncStandardMapper.selectNcStandardList(ncStandard);
    }

    /**
     * 查询标准主列表
     *
     * @param ncStandard 标准主信息
     * @return 标准主集合
     */
    @Override
    public List<NcStandard> selectExportNcStandardList(NcStandard ncStandard) {

        List<NcStandard> ncStandards = ncStandardMapper.selectNcStandardList(ncStandard);

        if (ncStandards != null && ncStandards.size() > 0) {
            for (NcStandard standard : ncStandards) {
                NcStage stage = new NcStage();
                stage.setStandardId(standard.getStandardId());
                List<NcStage> ncStages = stageService.selectNcStageList(stage);
                if (ncStages != null && ncStages.size() > 0) {
                    standard.setStages(ncStages);
                    for (NcStage ncStage : ncStages) {
                        NcWork work = new NcWork();
                        work.setStageId(ncStage.getStageId());
                        workService.selectNcWorkList(work);


                    }


                }
            }


        }
        return ncStandardMapper.selectNcStandardList(ncStandard);
    }

    /**
     * 新增标准主
     *
     * @param ncStandard 标准主信息
     * @return 结果
     */
    @Override
    public int insertNcStandard(NcStandard ncStandard) {
        return ncStandardMapper.insertNcStandard(ncStandard);
    }

    /**
     * 修改标准主
     *
     * @param ncStandard 标准主信息
     * @return 结果
     */
    @Override
    public int updateNcStandard(NcStandard ncStandard) {
        return ncStandardMapper.updateNcStandard(ncStandard);
    }

    /**
     * 删除标准主对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteNcStandardByIds(String ids) {
        return ncStandardMapper.deleteNcStandardByIds(Convert.toStrArray(ids));
    }

    @Override
    public NcStandard fillValues(NcStandard ncStandard, String parentCode) {
        //找到菜 并找到这个菜的父类，祖父类
        NcCai ncCai = ncCaiService.selectCaiById(ncStandard.getCropVarieties());
        if (ncCai == null || ncCai.getAncestors() == null || ncCai.getAncestors().split(",").length != 3) {
            return null;
        }
        //蔬菜名称
        NcCai cropNameBean = ncCaiService.selectCaiById(ncCai.getParentId());
        //蔬菜分类
        NcCai cropTypeBean = ncCaiService.selectCaiById(cropNameBean.getParentId());

        ncStandard.setCropVarietiesCn(ncCai.getCaiName());
        ncStandard.setCropNameCn(cropNameBean.getCaiName());
        ncStandard.setCropTypeCn(cropTypeBean.getCaiName());

        //找到这个菜的标准数量
        NcStandard standard = new NcStandard();
        standard.setCropVarieties(ncStandard.getCropVarieties());

        /*设置编码*/
        List<NcStandard> ncStandards = selectNcStandardList(standard);
        ncStandard.setCode(NcUtils.getStandardCode(ncStandards.size()));
        ncStandard.setParentCode("000");

        ncStandard.setStandardName(
                ncStandard.getCropTypeCn() +
                        "-" + ncStandard.getCropNameCn() +
                        "-" + ncStandard.getCropVarietiesCn() +
                        "-" + ncStandard.getSeason() +
                        "-" + ncStandard.getParentCode() +
                        "-" + ncStandard.getCode());

        return ncStandard;
    }

    @Override
    public List<NcStandard> selectNcStandardListByIds(String ids) {
        return ncStandardMapper.selectNcStandardListByIds(Convert.toStrArray(ids));
    }


    @Override
    public List<ShowNcStandard> showNcStandard(String standardType) {
        return ncStandardMapper.showNcStandard(standardType);
    }

    @Override
    public Map getStatusCount(NcStandard ncStandard) {
        List<Map> maps = selectSum(ncStandard);
        int total = 0;
        for (Map m : maps) {
            total += NcUtils.getCount(m, "amount");
        }
        Map map = new HashMap();
        map.put("total", total);
        return map;

    }

    @Override
    public List<Map> selectSum(NcStandard ncStandard) {
        return ncStandardMapper.selectSum(ncStandard);
    }

    /*获取各大菜分类下的计划数量*/
    @Override
    public List<NcCai> getBigCaiClass(NcStandard ncStandard) {
        //1、计算温室数量
        NcCai cai = new NcCai();
        cai.setAncestors("0");
        cai.setParentId(new Long(0));
        List<NcCai> result = ncCaiService.selectBigClass(cai);
        //过滤
        for (NcCai c : result) {
            //遍历取计划数量数量
            ncStandard.setStandardType(ncStandard.getStandardType());
            ncStandard.getParams().put("ancestors", c.getCaiId());
            c.setPlanCounts(getStatusCount(ncStandard));

        }
        //计算占比
        Integer total = 0;
        Integer prePlan = 0;
        Integer onPlan = 0;
        Integer finished = 0;
        for (NcCai c : result) {
            Map counts = c.getPlanCounts();
            total += NcUtils.getCount(counts, "total");
            prePlan += NcUtils.getCount(counts, "prePlan");
            onPlan += NcUtils.getCount(counts, "onPlan");
            finished += NcUtils.getCount(counts, "finished");

        }

        for (NcCai c : result) {
            Map counts = c.getPlanCounts();
            counts.put("total_rate", NcUtils.getRate(total, counts, "total"));
            counts.put("prePlan_rate", NcUtils.getRate(prePlan, counts, "prePlan"));
            counts.put("onPlan_rate", NcUtils.getRate(onPlan, counts, "onPlan"));
            counts.put("finished_rate", NcUtils.getRate(finished, counts, "finished"));
        }
        //统计数量
        return result;
    }

    @Override
    public String importNcStandard(List<NcStandard> ncStandardList, boolean isUpdateSupport, String operName) {

        if (StringUtils.isNull(ncStandardList) || ncStandardList.size() == 0) {
            throw new BusinessException("导入标准数据不能为空！");
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        for (NcStandard standard : ncStandardList) {
            try {
                // 验证是否存在这个标准
                NcStandard s = ncStandardMapper.selectStandardByStandardName(standard.getStandardName());
                if (StringUtils.isNull(s)) {
                    standard.setCreateBy(operName);
                    this.insertNcStandard(standard);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、标准 " + standard.getStandardName() + " 导入成功");
                } else if (isUpdateSupport) {
                    standard.setUpdateBy(operName);
                    this.updateNcStandard(standard);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、标准 " + standard.getStandardName() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、标准 " + standard.getStandardName() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、标准 " + standard.getStandardName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }


        return null;
    }


    @Override
    @Transactional
    public AjaxResult importNcStandard(SysUser sysUser, String standardType, MultipartFile file, boolean updateSupport) {

        StringBuilder message = new StringBuilder();

        try {

            InputStream inputStream = file.getInputStream();

            boolean ooxml = ExcelUtils.isOOXML(inputStream);

            Workbook workbook = null;

            try {
                if (ooxml) {
                    workbook = new XSSFWorkbook(file.getInputStream());
                } else if (!ooxml) {
                    workbook = new HSSFWorkbook(file.getInputStream());
                }
            } catch (IOException e) {
                e.printStackTrace();

            }


            if (workbook == null) {
                return AjaxResult.error("工作簿为空");
            } else if (workbook.getNumberOfSheets() == 0) {
                return AjaxResult.error("工作簿为空");
            }


            Row row = null;

            //分别获取Sheet

            Sheet ncStandsSheet = workbook.getSheetAt(0);
            Sheet ncStageSheet = workbook.getSheetAt(1);
            Sheet ncWorksSheet = workbook.getSheetAt(2);

            ArrayList<NcStandard> standards = new ArrayList<>();
            ArrayList<NcStage> ncStages = new ArrayList<>();
            ArrayList<NcWork> ncWorks = new ArrayList<>();


            //循环标准


            if (ncStandsSheet.getLastRowNum() == 0) {
                return AjaxResult.error("第一张表 ncStands为空");

            }

            if (ncStageSheet.getLastRowNum() == 0) {
                return AjaxResult.error("第二张表 ncStage为空");

            }

            if (ncWorksSheet.getLastRowNum() == 0) {
                return AjaxResult.error("第三张表 ncWorks为空");

            }


            NcStandard ncStandard = null;
            for (int i = ncStandsSheet.getFirstRowNum() + 1; i < ncStandsSheet.getLastRowNum() + 1; i++) {
                row = ncStandsSheet.getRow(i);
                if (row == null || row.getCell(1) == null) {
                    continue;
                }
                ncStandard = new NcStandard();
                ncStandard.setStandardType(standardType);

                ncStandard.setCreateBy(sysUser.getLoginName());

                ncStandard.setCreateTime(new Date());

                //标准序号
                ncStandard.setSerialStandardNumber(NcUtils.getDouble(row.getCell(0)));

                //作物类别
                String cropTypeCn = NcUtils.getStr(row.getCell(1));

                //作物名称
                String cropNameCn = NcUtils.getStr(row.getCell(2));

                //作物品种
                String cropVarietiesCn = NcUtils.getStr(row.getCell(3));


                //校验作物是否存在

                NcCai cai = new NcCai();
                cai.setCaiName(cropVarietiesCn);


                List<NcCai> ncCais = ncCaiService.selectCaiList(cai);
                ncCais.removeIf(thisCai -> thisCai.getAncestors().split(",").length != 3);

                boolean caiFlag = true;

                if (ncCais != null && ncCais.size() > 0) {
                    for (NcCai ncCaiDB : ncCais) {
                        Long caiId = ncCaiDB.getCaiId();
                        NcCai caiParent = ncCaiService.selectCaiById(ncCaiDB.getParentId());
                        String cropNameCnDB = caiParent.getCaiName();
                        String cropTypeCnDB = ncCaiService.selectCaiById(caiParent.getParentId()).getCaiName();
                        //判断作物是否存在
                        if (cropNameCn.equals(cropNameCnDB) && cropTypeCn.equals(cropTypeCnDB)) {
                            ncStandard.setCropVarieties(ncCaiDB.getCaiId());
                            ncStandard.setCropTypeCn(cropTypeCn);
                            ncStandard.setCropNameCn(cropNameCn);
                            ncStandard.setCropVarietiesCn(cropVarietiesCn);
                            caiFlag = false;
                            break;
                        }
                    }
                }

                if (caiFlag) {
                    return AjaxResult.error("第【" + (i + 1) + "】行数据中作物【" + cropVarietiesCn + "】不存在");
                }

                //适宜季节
                String season = NcUtils.getStr(row.getCell(4));
                if ("春".equals(season)) {
                    ncStandard.setSeason("1");
                } else if ("夏".equals(season)) {
                    ncStandard.setSeason("2");
                } else if ("秋".equals(season)) {
                    ncStandard.setSeason("3");
                } else if ("冬".equals(season)) {
                    ncStandard.setSeason("4");
                } else if ("四季".equals(season)) {
                    ncStandard.setSeason("5");
                }


                //总周期
                String totalCycle = NcUtils.getStr(row.getCell(5));
                ncStandard.setTotalCycle(totalCycle);


                //备注
                String remark = NcUtils.getStr(row.getCell(6));
                ncStandard.setRemark(remark);


                //删除标志
                ncStandard.setDelFlag("1");
                //状态码
                ncStandard.setStatus("2");


                ncStandard.setParentCode("000");
                //标准名称
                StringBuilder standardName = new StringBuilder();

                standardName.append(cropNameCn);
                standardName.append("-");
                standardName.append(cropVarietiesCn);
                standardName.append("-");
                standardName.append("000");
                standardName.append("-");
                //查询该作物标准的数量


                if (ncCais.size() != 0) {
                    standardName.append("-");
                    standardName.append(ncCais.size());
                }

                ncStandard.setStandardName(standardName.toString());

                standards.add(ncStandard);

            }


            //循环阶段
            for (int j = ncStageSheet.getFirstRowNum() + 1; j < ncStageSheet.getLastRowNum() + 1; j++) {
                row = ncStageSheet.getRow(j);
                if (row == null || row.getCell(0) == null || row.getCell(1) == null || row.getCell(2) == null) {
                    continue;
                }
                NcStage ncStage = new NcStage();
                ncStage.setCreateBy(sysUser.getLoginName());
                ncStage.setCreateTime(new Date());

                //标准序号
                ncStage.setSerialStandardNumber(NcUtils.getDouble(row.getCell(0)));

                //阶段序号
                ncStage.setSerialStageNumber(NcUtils.getDouble(row.getCell(1)));

                //阶段名称
                String stageName = NcUtils.getStr(row.getCell(2));
                ncStage.setStageName(stageName);

                //阶段天数
                Integer stageDays = NcUtils.getInteger(row.getCell(3));
                ncStage.setStageDays(stageDays);

                //排序号
                ncStage.setOrderNum(NcUtils.getInteger(row.getCell(4)));

                //阶段描述
                String stageDetail = NcUtils.getStr(row.getCell(5));
                ncStage.setStageDetail(stageDetail);

                //阶段备注
                String remark = NcUtils.getStr(row.getCell(6));
                ncStage.setRemark(remark);


                ncStages.add(ncStage);

            }


            //循环工作
            for (int k = ncWorksSheet.getFirstRowNum() + 1; k < ncWorksSheet.getLastRowNum() + 1; k++) {
                row = ncWorksSheet.getRow(k);
                if (row == null || row.getCell(0) == null || row.getCell(1) == null || row.getCell(2) == null) {
                    continue;
                }
                NcWork ncWork = new NcWork();
                ncWork.setCreateBy(sysUser.getLoginName());
                ncWork.setCreateTime(new Date());


                //标准序号
                ncWork.setSerialStandardNumber(NcUtils.getDouble(row.getCell(0)));

                //阶段序号
                ncWork.setSerialStageNumber(NcUtils.getDouble(row.getCell(1)));

                //农事名称
                String workName = NcUtils.getStr(row.getCell(2));
                ncWork.setWorkName(workName);

                //农事类型
                String workType = NcUtils.getStr(row.getCell(3));
                if ("栽培".equals(workType)) {
                    ncWork.setWorkType("1");
                } else if ("农资".equals(workType)) {
                    ncWork.setWorkType("2");

                }


                //循环周期
                ncWork.setCycleDays(NcUtils.getInteger(row.getCell(4)));

                //第几天开始
                ncWork.setWorkStart(NcUtils.getInteger(row.getCell(5)));

                //第几天结束
                ncWork.setWorkEnd(NcUtils.getInteger(row.getCell(6)));

                //动态调整
                String isDynamic = NcUtils.getStr(row.getCell(7));
                if ("不是".equals(workType)) {
                    ncWork.setIsDynamic("0");
                } else if ("是".equals(workType)) {
                    ncWork.setIsDynamic("1");
                }

                //农资名称
                String inputCn = NcUtils.getStr(row.getCell(8));
                ncWork.setInputCn(inputCn);


                //数量
                ncWork.setInputCount(NcUtils.getInteger(row.getCell(9)));


                //校验农资数量
//                meterialService.selectMeterialIdByName()

                //单位
                String inputUnit = NcUtils.getStr(row.getCell(10));
                ncWork.setInputUnit(inputUnit.split("\\.")[0]);

                //工作内容
                String workDetail = NcUtils.getStr(row.getCell(11));
                ncWork.setWorkDetail(workDetail);

                String remark = NcUtils.getStr(row.getCell(12));
                ncWork.setRemark(remark);

                ncWorks.add(ncWork);
            }


            for (NcStandard standard : standards) {

                this.insertNcStandard(standard);
                Long standardId = standard.getStandardId();

                for (NcStage ncStage : ncStages) {

                    if (ncStage.getSerialStandardNumber().equals(standard.getSerialStandardNumber())) {
                        ncStage.setStandardId(standardId);
                    }
                }
            }


            for (NcStage ncStage : ncStages) {
                stageService.insertNcStage(ncStage);
                Long stageId = ncStage.getStageId();
                for (NcWork ncWork : ncWorks) {
                    if (ncWork.getSerialStandardNumber().equals(ncStage.getSerialStandardNumber())) {
                        ncWork.setStandardId(ncStage.getStandardId());
                    }
                    if (ncWork.getSerialStageNumber().equals(ncStage.getSerialStageNumber())) {
                        ncWork.setStageId(stageId);
                    }
                }
            }

            for (NcWork ncWork : ncWorks) {
                workService.insertNcWork(ncWork);
            }
            return AjaxResult.success("导入成功");

        } catch (IOException e) {
            e.printStackTrace();

        }
        return null;
    }

    @Override
    @Transactional
    public int createStandardByPlan(Long plandId, SysUser user) {
        /**计划*/
        NcPlan plan = planService.selectNcPlanById(plandId);
        if (plan == null || plan.getPlanId() == null) {
            return 0;
        }
        /**计划对应的标准*/
        NcStandard parent = selectNcStandardById(plan.getStandardId());
        if (parent == null || parent.getStandardId() == null) {
            return 0;
        }

        /**1、创建标准*/
        NcStandard st = createStandard(parent, plandId, user);
        /**2、查找阶段*/

        NcStageMirror stm = new NcStageMirror();
        stm.setPlanId(plandId);
        stm.setStandardId(parent.getStandardId());
        List<NcStageMirror> stageMirrors = stageMirrorService.selectNcStageMirrorList(stm);
        //根据计划的开始时间 和每个阶段的完成时间计算每个阶段的花费时间
        stageMirrors = fillDateSpan(plan, stageMirrors);

        /**3、查找农事*/
        List<NcWork> works = getWorks(stageMirrors, plan);
        //保存
        int code = insertNcStandard(st);
        if (code > 0) {
            //插入阶段
            for (NcStageMirror sm : stageMirrors) {
                sm.setStandardId(st.getStandardId());

                NcStage stage = new NcStage(sm);
                stageService.insertNcStage(stage);
                //插入农事
                for (NcWork work : works) {
                    if (sm.getStageMirrorId().equals(work.getStageId())) {
                        work.setStageId(stage.getStageId());
                        workService.insertNcWork(work);
                        continue;
                    }

                    if (sm.getStageId().equals(work.getStageId())) {
                        work.setStageId(stage.getStageId());
                        workService.insertNcWork(work);
                    }
                }
            }

            return 1;
        } else {
            return 0;
        }
    }

    /*查找农事*/
    private List<NcWork> getWorks(List<NcStageMirror> stageMirrors, NcPlan plan) {
        List<NcWork> result = new ArrayList<>();
        //非周期农事
        List<NcWorkLog> works = new ArrayList<>();
        //周期农事
        NcWorkMirror wm = new NcWorkMirror();
        wm.setPlanId(plan.getPlanId());
        wm.getParams().put("isCycle", 1);
        List<NcWorkMirror> cycleWorks = workMirrorService.selectNcWorkMirrorList(wm);



        /*阶段的开始*/
        Date start = DateUtils.addDays(plan.getPlanTime(), -1);
        for (NcStageMirror m : stageMirrors) {
            //农事记录 只取非周期性的
            NcWorkLog nw = new NcWorkLog();
            nw.setStageId(m.getStageMirrorId());
            nw.setPlanId(m.getPlanId());
            nw.getParams().put("notCycle", 1);
            List<NcWorkLog> workLogs = workLogService.selectNcWorkLogList(nw);
            //根据结束日期计算是阶段的第几天
            for (NcWorkLog log : workLogs) {
                int days = NcUtils.differentDaysByDate(log.getCreateTime(), start);
                log.setWorkStart(days <= 0 ? 1 : days);
                log.setWorkEnd(null);
            }
            start = m.getFinishTime();

            works.addAll(workLogs);
        }
        for (NcWorkLog log : works) {
            NcWork nw = new NcWork(log);
            result.add(nw);
        }
        for (NcWorkMirror cm : cycleWorks) {
            NcWork nw = new NcWork(cm);
            result.add(nw);
        }
        return result;
    }

    /**
     * 根据计划的开始时间 和每个阶段的完成时间计算每个阶段的花费时间
     */
    private List<NcStageMirror> fillDateSpan(NcPlan plan, List<NcStageMirror> stageMirrors) {
        //开始时间
        Date startDate = DateUtils.addDays(plan.getPlanTime(), -1);
        for (NcStageMirror st : stageMirrors) {
            int days = NcUtils.differentDaysByDate(st.getFinishTime(), startDate);
            st.setStageDays(days <= 0 ? 1 : days);
            startDate = st.getFinishTime();
        }
        return stageMirrors;
    }

    /*根据父标准创建子标准*/
    private NcStandard createStandard(NcStandard parent, Long plandId, SysUser user) {

        NcStandard st = new NcStandard();
        st.setPlanId(plandId);
        st.setPic(parent.getPic());
        st.setStandardType("" + parent.getStandardType());
        st.setSeason(parent.getSeason());

        st.setCropVarieties(parent.getCropVarieties());
        st.setCropNameCn(parent.getCropNameCn());
        st.setCropTypeCn(parent.getCropTypeCn());

        st.setRemark("计划产生标准");
        st.setCreateBy(user.getLoginName());
        st.setCreateTime(new Date());
        fillValues(st, parent.getCode());
        return st;
    }

}
